home *** CD-ROM | disk | FTP | other *** search
/ ...taking it to the Macs! / ...taking it to the Macs!.iso / Extras / ActiveX Mac SDK / ActiveX SDK / Sample Controls / Ticker / CTick.cpp next >
Encoding:
C/C++ Source or Header  |  1996-12-20  |  9.3 KB  |  388 lines  |  [TEXT/CWIE]

  1.  
  2. #include "ocheaders.h"
  3. #include "CBaseControl.h"
  4. #include "CErrorControl.h"
  5. #include "CTickerControl.h"
  6. #include "CTick.h"
  7. #include "FnAssert.h"
  8. #include "Colors.h"
  9. #include "CTickerError.h"
  10.  
  11.  
  12. ///////////////////////////////////////////////////////////////////////////////
  13. //
  14. //    CTick::CTick
  15. //
  16.  
  17. CTick::CTick( CTickerControl* pctl, long id )
  18. {
  19.     const Rect nullRect = { 0, 0, 0, 0 };
  20.     const Point nullSize = { 0, 0 };
  21.  
  22.     mDataItemID    = id;
  23.     mControl         = pctl;
  24.     mCached        = false;
  25.     mXLocation             = 0;
  26.     mFontInfo        = NULL;
  27.     mSize            = nullSize;
  28.     mBoundsRect     = nullRect;
  29.     mGWorld         = NULL;
  30.     mPixMap        = NULL;
  31.     mStrName         = NULL;
  32.     mStrValue         = NULL;
  33.     mRenderState    = renderOFF;
  34. }
  35.  
  36. ///////////////////////////////////////////////////////////////////////////////
  37. //
  38. //    CTick::~CTick
  39. //
  40.  
  41. CTick::~CTick()
  42. {
  43.     Render(renderOFF); // avoid code duplication by calling Render() directly
  44.     
  45.     if ( mFontInfo )
  46.     {
  47.         ::CoTaskMemFree(mFontInfo);
  48.         mFontInfo = NULL;
  49.     }
  50.     
  51.     if ( mStrName )
  52.     {
  53.         ::CoTaskMemFree(mStrName);
  54.         mStrName = NULL;
  55.     }
  56.     if ( mStrValue )
  57.     {
  58.         ::CoTaskMemFree(mStrValue);
  59.         mStrValue = NULL;
  60.     }
  61. }
  62.  
  63.  
  64. ///////////////////////////////////////////////////////////////////////////////
  65. //
  66. //    CTick::Render
  67. //
  68. //  Synopsis:   Creates an offscreen gworld with the text rendered in it.  
  69. //
  70.  
  71. void CTick::Render(RenderState renderState) 
  72. {
  73.     if ( renderState == renderON && mRenderState == renderOFF)
  74.     {
  75.         try
  76.         {
  77.             // Compute the bounds of the offscreen gworld, as determined by the 
  78.             // text when it's draw in its characteristic offset mode.
  79.  
  80.             // Does this tick have a value?
  81.             Boolean isValue = (strlen(mStrValue) != 0);
  82.             
  83.             // Get the size of the name
  84.             Point sizeName  = {0,0};
  85.             Str255 strName;
  86.             strcpy((char *)strName, mStrName);
  87.             strcat((char *)strName, " ");
  88.             if (isValue)
  89.                 strcat((char *)strName, " ");
  90.             c2pstr((char *)strName);
  91.             GetTextSize(strName, &sizeName);
  92.  
  93.             // Get the size of the value(s)
  94.             Point sizeValue = {0,0};
  95.             if (isValue)
  96.             {
  97.                 Str255 strValue;
  98.                 strcpy((char *)strValue, mStrValue);
  99.                 strcat((char *)strValue, "  ");
  100.                 c2pstr((char *)strValue);
  101.                 GetTextSize(strValue, &sizeValue);
  102.             }
  103.             
  104.             // Text sizes
  105.             mSize.v = sizeName.v > sizeValue.v ? sizeName.v : sizeValue.v;
  106.             mSize.h = sizeName.h + sizeValue.h;
  107.  
  108.             // Offset the names from the values
  109.             short offsetBy = (mSize.v / 3); // the default is dependent on text height
  110.             if ( mControl->GetUserOffsetValues() ) // did the user specify in a parameter?
  111.                 offsetBy = mControl->GetOffsetValues(); // use the input value instead
  112.             mSize.v += ABSVAL(offsetBy); // adjust text height for the offset, whatever it is
  113.                 
  114.             // set the size of the offscreen gworld
  115.             ::SetRect(&mBoundsRect, 0, 0, mSize.h, mSize.v);
  116.             
  117.             // we shouldn't already have a gworld
  118.             ASSERT((mGWorld == NULL), "Unexpected non-NULL GWorld!");
  119.             ASSERT((mPixMap == NULL), "Unexpected non-NULL PixMap!");
  120.  
  121.             // make the new gworld if needed
  122.             mPixMap = NULL;
  123.             QDErr err = ::NewGWorld( &mGWorld, 8, &mBoundsRect, 0, nil, 0 );
  124.             if ( !err )
  125.                 mPixMap = ::GetGWorldPixMap( mGWorld );
  126.                 
  127.             // NOW we should have a gworld
  128.             if ( mGWorld == NULL || mPixMap == NULL )
  129.                 throw CTickerError(TICK_GWORLD_ALLOCATION_ERROR, this);
  130.             
  131.             // Store the current port and device before switching to the offscreen world.
  132.             CGrafPtr    currentPort;
  133.             GDHandle    currentDevice;
  134.             ::GetGWorld( ¤tPort, ¤tDevice );
  135.  
  136.             // Switch to the offscreen GWorld and lock the offscreen buffer in memory.
  137.             ::SetGWorld( mGWorld, nil );
  138.             ::LockPixels( mPixMap );
  139.             ::HLock((Handle)mPixMap);
  140.  
  141.             // Draw the text into the offsceen world...
  142.                     
  143.             // generate Pascal strings for drawing
  144.             Str255 nameStringToDraw, valueStringToDraw;
  145.             strcpy((char *)nameStringToDraw, mStrName);
  146.             c2pstr((char *)nameStringToDraw);
  147.             strcpy((char *)valueStringToDraw, mStrValue);
  148.             c2pstr((char *)valueStringToDraw);
  149.             
  150.             // Set colors
  151.             RGBColor foreColor, backColor;
  152.             mControl->GetBackColor(&backColor);
  153.             mControl->GetForeColor(&foreColor);
  154.             ::RGBBackColor(&backColor);
  155.             ::RGBForeColor(&foreColor);
  156.  
  157.             // Erase.
  158.             EraseImage();
  159.             
  160.             // Set font characteristics
  161.             SetFontParams();
  162.             
  163.             // Actually draw the strings
  164.             ::MoveTo(0, mFontInfo->ascent + (offsetBy < 0 ? -offsetBy : 0));
  165.             ::DrawString(nameStringToDraw);
  166.             ::MoveTo(sizeName.h, (mFontInfo->ascent + offsetBy));
  167.             ::DrawString(valueStringToDraw);
  168.  
  169.             // After drawing the image, unlock the offscreen buffer in memory
  170.             //  and set the port and device back to the original        
  171.             ::HUnlock((Handle)mPixMap);
  172.             ::UnlockPixels( mPixMap );
  173.             ::SetGWorld( currentPort, currentDevice );
  174.             
  175.             // set the current state so we don't re-render
  176.             mRenderState = renderON;
  177.         }
  178.         
  179.         // error handling
  180.         catch ( CTickerError &tickerError )
  181.         {
  182.             tickerError.HandleError();
  183.         }
  184.     }
  185.     else if ( renderState == renderOFF ) // (it's OK to set renderOFF repeatedly)
  186.     {
  187.         // unrender anything that we don't need right now, so that
  188.         // we optimize for memory.
  189.         if ( mGWorld )
  190.         {
  191.             ::DisposeGWorld( mGWorld );
  192.             mGWorld = NULL;
  193.             mPixMap = NULL;
  194.             mRenderState = renderOFF;
  195.         }
  196.     }
  197. }
  198.  
  199. ///////////////////////////////////////////////////////////////////////////////
  200. //
  201. //    CTick::EraseImage
  202. //
  203.  
  204. void CTick::EraseImage() 
  205. {
  206.     ASSERT(mPixMap != NULL, "CTick::EraseImage: Null pixmap!");
  207.     
  208.     // Erase the PixMap's bounding box in the GWorld.
  209.     ::EraseRect( &((**mPixMap).bounds) );
  210. }
  211.  
  212. ///////////////////////////////////////////////////////////////////////////////
  213. //
  214. //    CTick::SetFontParams
  215. //
  216.  
  217. void CTick::SetFontParams()
  218. {
  219.     // a future hook for actual PARAMs
  220.     ::TextFace(bold);
  221.     ::TextFont(applFont);
  222.     ::TextSize(9);
  223.     ::TextMode(srcCopy);
  224. }
  225.  
  226. ///////////////////////////////////////////////////////////////////////////////
  227. //
  228. //    CTick::SaveFontParams
  229. //
  230.  
  231. void CTick::SaveFontParams()
  232. /*
  233.     m_SavedFontParams.textFace = qd.thePort->txFace;
  234.     m_SavedFontParams.textFont = qd.thePort->txFont;
  235.     m_SavedFontParams.textSize = qd.thePort->txSize;
  236.     m_SavedFontParams.textMode = qd.thePort->txMode; 
  237. */
  238. }
  239.  
  240. ///////////////////////////////////////////////////////////////////////////////
  241. //
  242. //    CTick::ResetFontParams
  243. //
  244.  
  245. void CTick::ResetFontParams()
  246. {
  247. /*
  248.     TextFace(m_SavedFontParams.textFont);
  249.     TextFont(m_SavedFontParams.textFace);
  250.     TextSize(m_SavedFontParams.textSize);
  251.     TextMode(m_SavedFontParams.textMode);
  252. */
  253. }
  254.  
  255. ///////////////////////////////////////////////////////////////////////////////
  256. //
  257. //    CTick::GetTextSize
  258. //
  259.  
  260. void CTick::GetTextSize(const StringPtr aString, Point * textSize)
  261. {
  262.     InitFontInfo();
  263.  
  264.     textSize->v = mFontInfo->ascent + mFontInfo->descent;     // compute height
  265.     
  266.     textSize->h = StringWidth(aString);                             // compute width
  267. }
  268.  
  269. ///////////////////////////////////////////////////////////////////////////////
  270. //
  271. //    CTick::InitFontInfo
  272. //
  273.  
  274. void CTick::InitFontInfo(void)
  275. {
  276.     if ( mFontInfo == NULL )
  277.         mFontInfo = (FontInfo *) ::CoTaskMemAlloc(sizeof(FontInfo));
  278.  
  279.     if ( mFontInfo == NULL )
  280.         throw CTickerError(FONTINFO_ALLOCATION_ERROR);
  281.         
  282.     SaveFontParams();     // save off the current params
  283.     SetFontParams();         // set the new info in the CURRENT grafport!
  284.  
  285.     ::GetFontInfo(mFontInfo);
  286.     
  287.     ResetFontParams();    // set everything back
  288. }
  289.  
  290. ///////////////////////////////////////////////////////////////////////////////
  291. //
  292. //    CTick::GetBitMap
  293. //
  294.  
  295. BitMap * CTick::GetBitMap(void)
  296. {
  297.     ASSERT((mPixMap != NULL), "CTick::GetBitMap: NULL pixMap!");
  298.     ::LockPixels( mPixMap );
  299.     ::HLock((Handle)mPixMap);
  300.     BitMap * theBitMap = (BitMap *)(*mPixMap);
  301.     ASSERT((theBitMap != NULL), "NULL bitmap!");
  302.     return theBitMap;
  303. }
  304.  
  305. ///////////////////////////////////////////////////////////////////////////////
  306. //
  307. //    CTick::ReleaseBitMap
  308. //
  309.  
  310. void CTick::ReleaseBitMap(void)
  311. {
  312.     ASSERT((mPixMap != NULL), "NULL pixMap!");
  313.     ::HUnlock((Handle)mPixMap);
  314.     ::UnlockPixels( mPixMap );
  315. }
  316.  
  317. ///////////////////////////////////////////////////////////////////////////////
  318. //
  319. //    CTick::SetName
  320. //
  321.  
  322. char * CTick::SetName(char * name)
  323. {
  324.     if ( mStrName )
  325.     {
  326.         ::CoTaskMemFree(mStrName);
  327.         mStrName = NULL;
  328.     }
  329.     
  330.     if ( name )
  331.     {
  332.         short length = strlen(name);
  333.         if ( length > MAX_STR_NAME_LENGTH )
  334.             length = MAX_STR_NAME_LENGTH;
  335.             
  336.         mStrName = (char *) ::CoTaskMemAlloc(length+1); // +1 for null term
  337.         if ( mStrName == NULL )
  338.             throw CTickerError(TICK_NAME_ALLOCATION_ERROR, this);
  339.         strncpy(mStrName, name, length);
  340.         mStrName[length] = 0; // null term
  341.     }
  342.     
  343.     return mStrName;
  344. }
  345.  
  346. ///////////////////////////////////////////////////////////////////////////////
  347. //
  348. //    CTick::SetValue
  349. //
  350.  
  351. char * CTick::SetValue(char * value)
  352. {
  353.     if ( mStrValue )
  354.     {
  355.         ::CoTaskMemFree(mStrValue);
  356.         mStrValue = NULL;
  357.     }
  358.     
  359.     if ( value )
  360.     {
  361.         short length = strlen(value) + 1; // +1 for extra space at end
  362.         if ( length > MAX_STR_NAME_LENGTH )
  363.             length = MAX_STR_NAME_LENGTH;
  364.             
  365.         mStrValue = (char *) ::CoTaskMemAlloc(length+1); // +1 for null term
  366.         if ( mStrName == NULL )
  367.             throw CTickerError(TICK_VALUE_ALLOCATION_ERROR, this);
  368.         strncpy(mStrValue, value, length-1);
  369.         strcat(mStrValue, " "); // extra space that we may remove with TruncateValue
  370.         mStrValue[length] = 0; // null term
  371.     }
  372.     
  373.     return mStrValue;
  374. }
  375.  
  376. ///////////////////////////////////////////////////////////////////////////////
  377. //
  378. //    CTick::SetValue
  379. //
  380.  
  381. void CTick::TruncateValue(short numberOfCharacters)
  382. {
  383.     short len = strlen(mStrValue);
  384.     if ( mStrValue && len > numberOfCharacters )
  385.         mStrValue[len-numberOfCharacters] = 0;
  386. }
  387.